package com.rfid.wlandirectlib;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.wifi.WifiManager;
import android.net.wifi.WpsInfo;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pGroup;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Handler;
import android.util.Log;

import androidx.annotation.NonNull;

import java.util.Collection;

public class WifiDirectManager implements WifiP2PListener {

    private static final String TAG = "WifiDirentManager";
    private WifiP2pManager mWifiP2pManager;
    private WifiP2pManager.Channel mChannel;

    private static WifiDirectManager manager;
    private boolean isInit = false;
    private WifiP2PBroadCastReceiver mWifiP2PBroadCastReceiver;
    private Context mContext;
    private WifiP2PListener mWifiP2PListener;
    private WifiGroupListener mWifiGroupListener;
    Handler mHandler = new Handler();

    public static WifiDirectManager getInstance() {
        if (manager == null) {
            manager = new WifiDirectManager();
        }
        return manager;
    }

    public void setListener(WifiP2PListener listener) {
        mWifiP2PListener = listener;
    }

    public void setGoupListener(WifiGroupListener listener) {
        mWifiGroupListener = listener;
    }

    public int initP2p(Context context) {
        // Device capability definition check
        if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)) {
            Log.e(TAG, "Wi-Fi Direct is not supported by this device.");
            return -1;
        }

        // Hardware capability check
        final WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (wifiManager == null) {
            Log.e(TAG, "Cannot get Wi-Fi system service.");
            return -2;
        }

//        if (!wifiManager.isP2pSupported()) {
//            Log.e(TAG, "Wi-Fi Direct is not supported by the hardware or Wi-Fi is off.");
//            return -3;
//        }

        mWifiP2pManager = (WifiP2pManager) context.getSystemService(Context.WIFI_P2P_SERVICE);
        if (mWifiP2pManager == null) {
            Log.e(TAG, "Cannot get Wi-Fi Direct system service.");
            return -4;
        }
        mChannel = mWifiP2pManager.initialize(context, context.getMainLooper(), null);
        if (mChannel == null) {
            Log.e(TAG, "Cannot initialize Wi-Fi Direct.");
            return -5;
        }
        isInit = true;
        mContext = context;
        mWifiP2pManager.requestConnectionInfo(mChannel, new WifiP2pManager.ConnectionInfoListener() {
            @Override
            public void onConnectionInfoAvailable(WifiP2pInfo info) {
                if (info != null) {
                    WifiDirectManager.this.onConnectionInfoAvailable(info);
                    System.out.println("info = " + info);
                }
            }
        });
        return 0;
    }

    @SuppressLint("MissingPermission")
    public void requestGroupInfo() {
        mWifiP2pManager.requestGroupInfo(mChannel, new WifiP2pManager.GroupInfoListener() {
            @Override
            public void onGroupInfoAvailable(WifiP2pGroup group) {
                if (group != null) {
                    onGroupInfoAvailable(group);
                    System.out.println(group.toString());
                }
            }
        });
    }

    public void destroy() {
        stopDiscovery();
        if (mWifiP2PBroadCastReceiver != null) {
            mWifiP2PBroadCastReceiver.unRegisterReceiver(mContext);
            mWifiP2PBroadCastReceiver.setListener(null);
        }
        mWifiGroupListener = null;
        isInit = false;
    }

    @SuppressLint("MissingPermission")
    public void createGroup() {
        mWifiP2pManager.createGroup(mChannel, new WifiP2pManager.ActionListener() {
            @Override
            public void onSuccess() {
                if (mWifiGroupListener != null) {
                    mWifiGroupListener.onCreateGroup(true);
                }
            }

            @Override
            public void onFailure(int reason) {
                Log.v(TAG,"createGroup reason = " + reason);
                System.out.println("createGroup reason = " + reason);
                if (mWifiGroupListener != null) {
                    mWifiGroupListener.onCreateGroup(false);
                }
            }
        });
    }

    public void removeGroup() {
        mWifiP2pManager.removeGroup(mChannel, new WifiP2pManager.ActionListener() {
            @Override
            public void onSuccess() {
                if (mWifiGroupListener != null) {
                    mWifiGroupListener.onRemoveGroup(true);
                }
            }

            @Override
            public void onFailure(int reason) {
                Log.v(TAG,"removeGroup reason = " + reason);
                if (mWifiGroupListener != null) {
                    mWifiGroupListener.onRemoveGroup(false);
                }
            }
        });
    }

    @SuppressLint("MissingPermission")
    public void discovery() {
        if (!isInit) {
            Log.e(TAG, "Please Init first!");
            return;
        }
        System.out.println("discovery");
        mWifiP2pManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
            @Override
            public void onSuccess() {
            }

            @Override
            public void onFailure(int reason) {
                System.out.println("discoverPeers fail reason = " + reason);
            }
        });
    }

    @SuppressLint("MissingPermission")
    public void startDiscovery() {
        if (!isInit) {
            Log.e(TAG, "Please Init first!");
            return;
        }
        mWifiP2PBroadCastReceiver = new WifiP2PBroadCastReceiver(mWifiP2pManager, mChannel);
        mWifiP2PBroadCastReceiver.registerReceiver(mContext);
        mWifiP2PBroadCastReceiver.setListener(this);
        mWifiP2pManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
            @Override
            public void onSuccess() {
                Log.e(TAG, "discoverPeers  onSuccess" );
            }

            @Override
            public void onFailure(int reason) {
                Log.e(TAG, "startDiscovery onFailure  reason = " + reason);
                System.out.println("discoverPeers fail reason = " + reason);
            }
        });
    }

    public void stopDiscovery() {
        if (!isInit) {
            Log.e(TAG, "Please Init first!");
            return;
        }
        mHandler.removeMessages(0);
        mWifiP2pManager.stopPeerDiscovery(mChannel, new WifiP2pManager.ActionListener() {
            @Override
            public void onSuccess() {
            }

            @Override
            public void onFailure(int reason) {
                Log.e(TAG,"onFailure reason = " + reason);
            }
        });
    }

    @SuppressLint("MissingPermission")
    public void connect(WifiP2pDevice device) {
        WifiP2pConfig config = new WifiP2pConfig();
        config.deviceAddress = device.deviceAddress;
        config.wps.setup = WpsInfo.PBC;
        mWifiP2pManager.connect(mChannel, config, new WifiP2pManager.ActionListener() {

            @Override
            public void onSuccess() {
                Log.e(TAG, "connect onSuccess!");
            }

            @Override
            public void onFailure(int reason) {
                Log.e(TAG, "connect onFailure  reason = " + reason);
            }
        });
    }

    public void cancelConnect() {
        mWifiP2pManager.cancelConnect(mChannel, new WifiP2pManager.ActionListener() {
            @Override
            public void onSuccess() {
            }

            @Override
            public void onFailure(int reason) {
            }
        });
    }

    @Override
    public void onWifiP2pEnabled(boolean isEnabled) {
        if (mWifiP2PListener != null) {
            mWifiP2PListener.onWifiP2pEnabled(isEnabled);
        }
    }

    @Override
    public void onDiscoverPeers(boolean isSuccess) {
        if (mWifiP2PListener != null) {
            mWifiP2PListener.onDiscoverPeers(isSuccess);
        }
    }

    @Override
    public void onSelfDeviceAvailable(@NonNull WifiP2pDevice wifiP2pDevice) {
        if (mWifiP2PListener != null) {
            mWifiP2PListener.onSelfDeviceAvailable(wifiP2pDevice);
        }
    }

    @Override
    public void onConnectionInfoAvailable(WifiP2pInfo wifiP2pInfo) {
        if (mWifiP2PListener != null) {
            mWifiP2PListener.onConnectionInfoAvailable(wifiP2pInfo);
        }
    }

    @Override
    public void onPeersAvailable(@NonNull Collection<WifiP2pDevice> wifiP2pDeviceList) {
        if (mWifiP2PListener != null) {
            mWifiP2PListener.onPeersAvailable(wifiP2pDeviceList);
        }
    }

    @Override
    public void onDiscoveryStatusChange(boolean isScan) {
/*        if (!isScan && isInit) {
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    discovery();
                }
            },500);
        }*/
        if (mWifiP2PListener != null) {
            mWifiP2PListener.onDiscoveryStatusChange(isScan);
        }
    }

    public void onGroupInfoAvailable(WifiP2pGroup group) {
        if (mWifiP2PListener != null) {
//            mWifiP2PListener.onGroupInfoAvailable(group);
        }
    }

}
